﻿using Dapper.Extensions;
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Http;
using YouWei.Api.Common;
using YouWei.Api.Models;
using YouWei.Api.WxPayAPI;
using YouWei.Infrastructure.Entity;
using YouWei.Infrastructure.Enums;
using YouWei.Infrastructure.Models;
using YouWei.Infrastructure.Service;
using YouWei.Utility;
using YouWei.Utility.Logging;

namespace YouWei.Api.Controllers
{
    /// <summary>
    /// 微信支付、分享相关
    /// </summary>
    public class WxPayController : BaseApiController
    {
        UserCardPayService usrCardPayService = new UserCardPayService();
        UserCardService cardService = new UserCardService();

        /// <summary>
        /// 获取支付字符串
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ResultData<string> Test()
        {
            string sql = @"<xml><appid><![CDATA[wx1b1e4f1de1ed9d0e]]></appid>
                            <bank_type><![CDATA[CFT]]></bank_type>
                            <cash_fee><![CDATA[1]]></cash_fee>
                            <fee_type><![CDATA[CNY]]></fee_type>
                            <is_subscribe><![CDATA[N]]></is_subscribe>
                            <mch_id><![CDATA[1503438781]]></mch_id>
                            <nonce_str><![CDATA[2989370365]]></nonce_str>
                            <openid><![CDATA[oJe-15OMNo4VVi9iS7iBWjRv-mC8]]></openid>
                            <out_trade_no><![CDATA[29_1126144701]]></out_trade_no>
                            <result_code><![CDATA[SUCCESS]]></result_code>
                            <return_code><![CDATA[SUCCESS]]></return_code>
                            <sign><![CDATA[03A69532D84FB6B2E8C6325F5791A4FF]]></sign>
                            <time_end><![CDATA[20191126144706]]></time_end>
                            <total_fee>1</total_fee>
                            <trade_type><![CDATA[JSAPI]]></trade_type>
                            <transaction_id><![CDATA[4200000438201911267876032834]]></transaction_id>
                            </xml>";
            WxMiniPayConfig config = new WxMiniPayConfig();
            WxPayData data = new WxPayData(config);

            data.FromXml(sql);

            if (data.GetValue("return_code").ToString() == "SUCCESS" && data.GetValue("result_code").ToString() == "SUCCESS")
            {
                string out_trade_no = data.GetValue("out_trade_no").ToString();
                int businessId = usrCardPayService.TradeNumToBusinessId(out_trade_no);
                if (businessId == 0)
                {
                    // return PayErrorBack("卡号不存在").ToXml();
                }

                try
                {
                    //交易单号
                    string transaction_id = data.GetValue("transaction_id").ToString();

                    if (usrCardPayService.PaySucess(transaction_id, businessId, BusinessTypeTypeEnum.UserCard))
                    {
                        data = PaySuccessBack();
                    }
                    else
                    {
                        data = PayErrorBack("支付失败");
                    }
                }
                catch (Exception ex)
                {
                    data = PayErrorBack(ex.Message);
                }
            }

            return null;
        }

        #region 发起支付

        /// <summary>
        /// 异步回调
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public string NotifyCallBack()
        {
            WxPayData data = GetNotifyData();
            if (data.GetValue("return_code").ToString() == "SUCCESS" && data.GetValue("result_code").ToString() == "SUCCESS")
            {
                string out_trade_no = data.GetValue("out_trade_no").ToString();
                int businessId = usrCardPayService.TradeNumToBusinessId(out_trade_no);
                if (businessId == 0)
                {
                    return PayErrorBack("卡号不存在").ToXml();
                }

                try
                {
                    //交易单号
                    string transaction_id = data.GetValue("transaction_id").ToString();

                    if (usrCardPayService.PaySucess(transaction_id, businessId, BusinessTypeTypeEnum.UserCard))
                    {
                        data = PaySuccessBack();
                    }
                    else
                    {
                        data = PayErrorBack("支付失败");
                    }
                }
                catch (Exception ex)
                {
                    data = PayErrorBack(ex.Message);
                }
            }

            return data.ToXml();
        }

        /// <summary>
        /// 接收从微信支付后台发送过来的数据并验证签名
        /// </summary>
        /// <returns>微信支付后台返回的数据</returns>
        public WxPayData GetNotifyData()
        {
            //接收从微信后台POST过来的数据
            System.IO.Stream s = HttpContext.Current.Request.InputStream;
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            while ((count = s.Read(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            s.Flush();
            s.Close();
            s.Dispose();

            Log4netLog.Info(new Utility.Logging.ActionLog()
            {
                CreatedDate = DateTime.Now,
                Platform = 4,
                PostData = builder.ToString(),
                RequestMethod = "WxPay",
                RequestUrl = Request.RequestUri.PathAndQuery
            });

            //转换数据格式并验证签名
            WxMiniPayConfig config = new WxMiniPayConfig();
            WxPayData data = new WxPayData(config);
            try
            {
                data.FromXml(builder.ToString());
            }
            catch (WxPayException ex)
            {
                //若签名错误，则立即返回结果给微信支付后台
                data = PayErrorBack(ex.Message);
            }
            return data;
        }

        /// <summary>
        /// 成功回调
        /// </summary>
        protected WxPayData PaySuccessBack()
        {
            WxPayData res = new WxPayData(null);
            res.SetValue("return_code", "SUCCESS");
            res.SetValue("return_msg", "OK");
            return res;
        }

        /// <summary>
        /// 失败回调
        /// </summary>
        /// <param name="msg"></param>
        protected WxPayData PayErrorBack(string msg)
        {
            Log4netLog.Error(new Utility.Logging.ErrorLog()
            {
                CreatedDate = DateTime.Now,
                Platform = 4,
                ErrorMessage = msg,
                RequestMethod = "WxPay",
                RequestUrl = Request.RequestUri.PathAndQuery
            });

            WxPayData res = new WxPayData(null);
            res.SetValue("return_code", "FAIL");
            res.SetValue("return_msg", msg);
            return res;
        }

        #endregion

        #region 发起支付

        /// <summary>
        /// 获取支付字符串
        /// </summary>
        /// <param name="businessId"></param>
        /// <param name="openId"></param>
        /// <returns></returns>
        [HttpGet]
        public ResultData<SortedDictionary<string, object>> TradeMiniPay(int businessId, string openId)
        {
            WxMiniPayConfig config = new WxMiniPayConfig();
            ResultData<SortedDictionary<string, object>> rdata = new ResultData<SortedDictionary<string, object>>();

            //decimal needPayPrice = orderInfo.NeedPayPrice * 100;
            var cards = cardService.GetCardByLevel(2);
            decimal needPayPrice = cards[0].PayPrice * 100;

            //防止订单号重复，以原始订单号为基础构造一个虚拟个订单号，在回调时再还原为原始订单号
            var out_trade_no = usrCardPayService.BusinessIdToTradeNum(businessId);

            WxPayApi WxApi = new WxPayApi(config);
            WxPayData payData = new WxPayData(config);
            payData.SetValue("appid", config.GetAppID());  //应用ID
            payData.SetValue("mch_id", config.GetMchID());  //商户号
            payData.SetValue("nonce_str", WxPayApi.GenerateNonceStr());

            payData.SetValue("body", "爱车仕会员卡");  //商品描述
            payData.SetValue("out_trade_no", out_trade_no); //商户订单号
            payData.SetValue("total_fee", Convert.ToInt32(needPayPrice));  //总金额
            payData.SetValue("trade_type", "JSAPI");  //交易类型
            payData.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));  //交易起始时间
            payData.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));  //交易结束时间
            payData.SetValue("notify_url", config.GetNotifyUrl());  //通知地址
            payData.SetValue("openid", openId);
            payData.SetValue("sign", payData.MakeSign(WxPayData.SIGN_TYPE_MD5));

            WxPayData rPayData = new WxPayData(config);
            try
            {

                rPayData = WxApi.UnifiedOrder(payData);
                Log4netLog.Debug(rPayData.ToJson());
                payData = new WxPayData(config);
                payData.SetValue("appId", config.GetAppID());  //预支付交易会话ID
                payData.SetValue("package", "prepay_id=" + rPayData.GetValue("prepay_id"));  //扩展字段
                payData.SetValue("signType", WxPayData.SIGN_TYPE_MD5);  //预支付交易会话ID
                payData.SetValue("nonceStr", WxPayApi.GenerateNonceStr());  //随机字符串
                payData.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());  //时间戳
                payData.SetValue("paySign", payData.MakeSign(WxPayData.SIGN_TYPE_MD5));  //签名
                rdata.data = payData.GetValues();
            }
            catch (Exception ex)
            {

                Log4netLog.Error(new Utility.Logging.ErrorLog()
                {
                    CreatedDate = DateTime.Now,
                    Platform = 4,
                    ErrorMessage = string.Format("支付成功但更新订单状态时出错,订单ID:{0}，错误原因:{1}", businessId, ex.Message),
                    RequestMethod = "WxPay",
                    RequestUrl = Request.RequestUri.AbsoluteUri
                });
                rdata.message = "支付时发生异常" + ex.ToString();
            }
            return rdata;
        }

        #endregion
    }
}
